/*********************************************************************************
 * Software License Agreement (BSD License)
 * Copyright (c) 2012, Carlos D. Correa (info@ngraph.org)
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of netzen nor the
 *    names of its contributors may be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************************/
#include "tabbar.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QListView>
#include <QTableView>
#include <QPushButton>
#include <QHeaderView>
#include <QCoreApplication>
#include <QLabel>
#include <QMap>

#include <QToolBox>

#include <assert.h>
#include "graph.h"
#include "qMappingEditor.h"
#include "glheaders.h"
#include "view.h"
#include "qDataEditor.h"

#include "propertyUtils.h"

Tabbar::Tabbar(Controller *controller, QWidget *parent): QWidget(parent) {
    QTabWidget *tabs = new QTabWidget();
    tabs->addTab(new Info(controller, this), tr("Info"));
    tabs->addTab(new Inspector(controller,this), tr("Inspector"));
    tabs->addTab(new Mapping(controller,this), tr("Mapping"));
    tabs->addTab(new Transforms(controller,this), tr("Analysis Tools"));
    tabs->addTab(new Layouts(controller,this), tr("Layouts"));

 //   tabs->addTab(new Datatab(controller,this), tr("Datatab")); //yuhsuan 0616 data tab

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(tabs);
    setLayout(mainLayout);
}

QStandardItemModel * createListModel(string list, Controller *controller) {
	QStandardItemModel *listModel = new QStandardItemModel();
	vector<string> nodeProps = controller->getRegisteredProperties(list);
	QStringList liststr;
	for(unsigned int i=0;i<nodeProps.size();i++) {
		string str, propType;
		if(nodeProps[i].find(Controller::addVirtualPrefix(""))!=string::npos) {
			string prefix = Controller::addVirtualPrefix("");
			str = nodeProps[i].substr(prefix.length());
			propType = "virtual";
		}
		else {
			str = nodeProps[i];
			propType = "real";
		}
		liststr << str.c_str();
		
		QStandardItem *item = new QStandardItem(QString(str.c_str()));
		listModel->setItem(i,0, item);
		item->setEditable(false);
		if(propType=="virtual") {
			item->setData(QFont("Arial", 12, QFont::Normal, true),Qt::FontRole);
		}
		QStandardItem *item2 = new QStandardItem(QString(nodeProps[i].c_str()));
		listModel->setItem(i,1, item2);
		item2->setEditable(false);
		
	}
	return listModel;
}
PropertyInspectorDelegate * createDelegate(Controller *controller,  QWidget *parent) {
    PropertyInspectorDelegate*  delegate = new PropertyInspectorDelegate(parent);

    vector<string> lists = controller->getRegisteredLists();
    for(unsigned int k=0;k<lists.size();k++) {
			QStandardItemModel *listModel = createListModel(lists[k], controller);
			/*
			listModel->setStringList(list);
			listModel->setData(listModel->index(0),myFont, Qt::FontRole);
			listModel->setData(listModel->index(2),myFont, Qt::FontRole);
			listModel->setData(listModel->index(3),myFont, Qt::FontRole);
			//listModel->setItemData(1, tr("Hello"), Qt::UserRole);
			 */
			 
			delegate->addStringModel(lists[k], listModel);
			//QVariant var = listModel->data(listModel->index(0), Qt::FontRole);
    }
    return delegate;
}

Info::Info(Controller *controller, QWidget *parent):QWidget(parent) {
    this->controller = controller;
    controller->addDataListener(this);
    QVBoxLayout *layout = new QVBoxLayout();

    sources = new QLabel("You have not loaded any data<br><br>Use <b>File</b>|<b> Import Table</b> to load node table");
    if(controller->sources.size()>0) {
        updateInfo();
    }
    layout->addWidget(sources);
    setLayout(layout);

}

void Info::updateInfo() {
    Graph *g = controller->getGraph("graph");
    string str;
    str = "<h3>Summary</h3><br><b>Sources:</b><br> ";
    for(unsigned int i=0; i<controller->sources.size();i++) {
        int len = controller->sources[i].length();
        string suffix = controller->sources[i].substr(max(0,len - 30));
        str+="..."+suffix+ "<br>";
    }
    char strNodes[256];
    char strEdges[256];
    sprintf(strNodes, "%d", (int) g->nodes.size());
    sprintf(strEdges, "%d", g->numEdges);
    str+="<br><br>";
    str+="<b>Num. nodes</b> &nbsp; &nbsp; " + string(strNodes) + "<br>";
    str+="<b>Num. edges</b> &nbsp; &nbsp; " + string(strEdges) + "<br>";
    sources->setText(str.c_str());
}
void Info::dataAdded(const char */*source*/, string /*event*/) {
    updateInfo();
}


void Inspector::viewAdded(View *view) {
	string type = view->getType();
	string name = view->getName();
	addView(type, name);
}

void Inspector::addView(string type, string name) {
    if(types.find(type) == types.end()) {
        QStandardItem *parentItem = new QStandardItem(QString(type.c_str()));
        parentItem->setEditable(false);
        root->appendRow(parentItem);
        types[type] = parentItem;
    }
    QStandardItem *item = new QStandardItem(QString(name.c_str()));
    item->setEditable(false);
	
		QStandardItem *item1 = new QStandardItem(QString(type.c_str()));
		item1->setEditable(true);
		//QList<QStandardItem *> items;
		//items.append(item);
		//items.append(item1);

		QStandardItem *parent = types[type];
    assert(parent);
    parent->appendRow(item);
		//item->setData(QFont("Verdana", 19, QFont::Bold, true),Qt::FontRole);
}


Inspector::Inspector(Controller *controller, QWidget *parent):QWidget(parent) {
    setWindowTitle("Inspector");
    this->controller = controller;
		QVBoxLayout* layout = new QVBoxLayout();

    tree = new QTreeView(this);

    model = new QStandardItemModel();

    vector<ViewInfo> views = controller->getViews();

    root = model->invisibleRootItem();
    for(unsigned int i=0;i<views.size();i++) {
			addView(views[i].type, views[i].name);
    }
	
    tree->setHeaderHidden(true);
    tree->setModel(model);
    connect(tree, SIGNAL(clicked(QModelIndex)), this, SLOT(clicked(QModelIndex)));
		layout->addWidget(tree);

    propertyTree = new QTreeView();
    propertyModel = new QStandardItemModel();
    connect(propertyModel, SIGNAL(itemChanged(QStandardItem *)), SLOT(propertyChanged(QStandardItem *)));

    propertyTree->setModel(propertyModel);
    propertyTree->setEditTriggers(QAbstractItemView::AllEditTriggers);
		layout->addWidget(propertyTree);
		//QTableView * table2 = new QTableView();
		//layout->addWidget(table2);
		propertyTree->setItemDelegate(createDelegate(controller, this));
	
		//toolBox = new QToolBox();
		//toolBox->setFont(QFont("Verdana", 10));
		//toolBox->addItem(table, tr("View"));
		//toolBox->addItem(table2, tr("Name"));
    //layout->addWidget(editor);
		//layout->addWidget(toolBox);

    setLayout(layout);
    currentView = 0;
    controller->addViewListener(this);
}

QTableView *Inspector::getTable(string name) {
	return tables[name];
}
QStandardItemModel *Inspector::getPropertyModel(string name) {
	return propertyModels[name];
}
QStandardItemModel *Inspector::createPropertyModel(string typeName) {
	QStandardItemModel* propertyModel = new QStandardItemModel();
	connect(propertyModel, SIGNAL(itemChanged(QStandardItem *)), SLOT(propertyChanged(QStandardItem *)));
	return propertyModel;
}
void Inspector::addPropertyModel(string name, QStandardItemModel *model) {
	propertyModels[name] = model;
}
void Inspector::createTable(string name, QStandardItemModel *model) {
	QTableView *table;
	table = new QTableView();
	table->setItemDelegate(createDelegate(controller, this));
	table->setModel(model);
	table->setEditTriggers(QAbstractItemView::AllEditTriggers);
	tables[name] = table;
	toolBox->addItem(table, tr(name.c_str()));
}
void Inspector::setupTable(string name) {
	QStandardItemModel *propertyModel = getPropertyModel(name);
	assert(propertyModel);
	propertyModel->setHeaderData(0, Qt::Horizontal, QString("Property"));
	propertyModel->setHeaderData(1, Qt::Horizontal, QString("Value"));
	QTableView *table = getTable(name);
	table->resizeColumnToContents(0);
	table->setColumnHidden(2, true);
	table->setColumnHidden(3, true);
	table->setColumnHidden(4, true);
	table->resizeColumnToContents(0);
	table->horizontalHeader()->setStretchLastSection(true);
}


/**
 Create table of properties separated into groups, automatically
 detected from naming of properties.
 Property name = group.name
 **/
void Inspector::clicked(const QModelIndex &index) {
	currentView = 0;
	QStandardItem *item = model->itemFromIndex(index);
	string name = item->data(Qt::EditRole).toString().toStdString();
	// Clear existing tables
	/*
	for(std::map<string, QStandardItemModel *>::iterator iter = propertyModels.begin(); iter != propertyModels.end(); ++iter) {
		iter->second->clear();
		if(tables[iter->first]) tables[iter->first]->setVisible(false);
	}
	propertyModels.clear();
	for(int i = toolBox->count()-1; i>=0; i--) {
		toolBox->removeItem(i);
	}
	*/
	View *view = controller->getView(name);
	if(view) {
			map<string, vector<string> > properties;
			vector<string> props = view->getProperties();
			for(unsigned int i=0;i<props.size();i++) {
				string typeName, name;
				PropertyUtils::parseProperty(props[i], typeName, name);
				properties[typeName].push_back(props[i]);
			}
			propertyModel->clear();
			propertyModel->setColumnCount(5);
			for(std::map<string, vector<string> >::iterator iter = properties.begin(); iter != properties.end(); ++iter) {
				string typeName = iter->first;
				vector<string> names = iter->second;
				/*
				QStandardItemModel *propertyModel = getPropertyModel(typeName);
				if(!propertyModel) {
					propertyModel = createPropertyModel(typeName);
					addPropertyModel(typeName, propertyModel);
					createTable(typeName, propertyModel);
				}
				assert(getTable(typeName));
				getTable(typeName)->setVisible(true);
				 */
				//printf("Creating root [%s]\n", typeName.c_str());
				QStandardItem *root = new QStandardItem(QString(typeName.c_str()));
				root->setEditable(false);
				root->setData(QFont("Arial", 12, QFont::Bold, false),Qt::FontRole);
				QList<QStandardItem*> rootRow;
				rootRow.append(root);
				for(int i=0;i<4;i++) {
					QStandardItem *item = new QStandardItem("");
					item->setEditable(false);
					rootRow.append(item);
				}

				propertyModel->appendRow(rootRow);
				propertyTree->setExpanded(root->index(), true);
				assert(propertyModel);
				for(unsigned int i=0;i<names.size();i++) {
					QList<QStandardItem *> items;
					string propName = names[i];
					string name;
					PropertyUtils::parseProperty(propName, typeName, name);
					QStandardItem *item = new QStandardItem(QString(name.c_str()));
					//propertyModel->setItem(i,0, item);
					item->setEditable(false);
					item->setData(QFont("Arial", 12, QFont::Bold, false),Qt::FontRole);
					items.append(item);

					string value = view->getAsString(propName);
					
					QStandardItem *item1 = new QStandardItem(QString(value.c_str()));
					//item1->setData(QFont("Arial", 12, QFont::Normal, false),Qt::FontRole);
					items.append(item1);
					//propertyModel->setItem(i,1, item1);

					int type = view->getPropertyType(propName);
					QStandardItem *item2 = new QStandardItem(QString("%0").arg(type));
					items.append(item2);
					//propertyModel->setItem(i,2, item2);

					string listModel = view->getPropertyListModel(propName);
					QStandardItem *item3 = new QStandardItem(QString(listModel.c_str()));
					items.append(item3);
					
					//propertyModel->setItem(i,3, item3);

					QStandardItem *item4 = new QStandardItem(QString(propName.c_str()));
					//propertyModel->setItem(i,4, item4);
					item4->setEditable(false);
					items.append(item4);
					root->appendRow(items);
				}
				
			}
	}
	propertyModel->setHeaderData(0, Qt::Horizontal, QString("Property"));
	propertyModel->setHeaderData(1, Qt::Horizontal, QString("Value"));
	//propertyTree->setIndentation(1);
	//propertyTree->setRootIsDecorated(true);
	propertyTree->setColumnHidden(2, true);
	propertyTree->setColumnHidden(3, true);
	propertyTree->setColumnHidden(4, true);
	propertyTree->expandAll();
	propertyTree->resizeColumnToContents(0);
	propertyTree->setColumnWidth(0, 200);
	propertyTree->header()->setStretchLastSection(true);
	for(std::map<string, QStandardItemModel *>::iterator iter = propertyModels.begin(); iter != propertyModels.end(); ++iter) {
		setupTable(iter->first);
	}
	

	currentView = view;
}

void Inspector::propertyChanged(QStandardItem *item) {
    if(!currentView) return;
    int row = item->index().row();
		assert(item->model());
    string value = item->data(Qt::EditRole).toString().toStdString();
    QStandardItem *itemProp = item->parent()->child(row,4);
		assert(itemProp);
    string property = itemProp->data(Qt::EditRole).toString().toStdString();

    controller->setViewProperty(currentView, property, value);
    currentView->update(property);
}

Mapping::Mapping(Controller *controller, QWidget *parent):QWidget(parent) {
    this->controller = controller;
    QVBoxLayout *layout = new QVBoxLayout();
    QMappingEditor *mapping = new QMappingEditor(controller, this);
    layout->addWidget(mapping);
    setLayout(layout);
}


/*********************** TRANSFORMS a.k.a. ANALYSIS TOOLS **************************/
Transforms::Transforms(Controller *controller, QWidget *parent):QWidget(parent) {
    setWindowTitle("Transform");
    this->controller = controller;

    QVBoxLayout *layout = new QVBoxLayout();

    vector<ToolInfo> tools = controller->getTools();

    // Create tree of transforms
    tree = new QTreeView(this);
    model = new QStandardItemModel();
    root = model->invisibleRootItem();
    for(unsigned int i=0;i<tools.size();i++) {
        string name = tools[i].name;
        string type = tools[i].type;

        if(types.find(type)==types.end()) {
            QStandardItem *parentItem = new QStandardItem(QString(type.c_str()));
            parentItem->setEditable(false);
            root->appendRow(parentItem);
            types[type] = parentItem;
        }
        QStandardItem *item = new QStandardItem(QString(name.c_str()));
        item->setEditable(false);
        QStandardItem *parent = types[type];
        assert(parent);
        parent->appendRow(item);
    }

    tree->setHeaderHidden(true);
    tree->setModel(model);
    connect(tree, SIGNAL(clicked(QModelIndex)), this, SLOT(clicked(QModelIndex)));



    table = new QTableView();
    propertyModel = new QStandardItemModel();
    connect(propertyModel, SIGNAL(itemChanged(QStandardItem *)), SLOT(propertyChanged(QStandardItem *)));

    table->setModel(propertyModel);
    table->setEditTriggers(QAbstractItemView::AllEditTriggers);


    QPushButton *button = new QPushButton("Go");
    connect(button, SIGNAL(clicked()), SLOT(computePressed()));


    progressBar = new QProgressBar();
    progressBar->setRange(0, 100);

    layout->addWidget(tree);
    layout->addWidget(table);
    layout->addWidget(button);
    layout->addWidget(progressBar);
    setLayout(layout);
}

void Transforms::setProgress(float value) {
    int iValue = (int) (value*100);
    progressBar->setValue(iValue);
    QCoreApplication::processEvents();
}
void Transforms::done() {
    progressBar->setValue(progressBar->maximum());
}

void Transforms::computePressed() {
    assert(controller);
    QItemSelectionModel * selection = tree->selectionModel();
    if(selection && selection->hasSelection()) {
        string name = selection->currentIndex().data().toString().toStdString();
        controller->executeTool(name);
    }
}

void Transforms::clicked(const QModelIndex &index) {
    assert(propertyModel);
    currentTool = 0;
    propertyModel->clear();

    QStandardItem *item = model->itemFromIndex(index);
    string name = item->data(Qt::EditRole).toString().toStdString();

    AnalysisTool *tool = controller->getTool(name);
    if(tool) {
        tool->setProgressListener(this);
        vector<string> props = tool->getProperties();

        for(unsigned int i=0;i<props.size();i++) {
            QStandardItem *item = new QStandardItem(QString(props[i].c_str()));
            propertyModel->setItem(i,0, item);
            item->setEditable(false);

					string value = tool->getAsString(props[i]);

            QStandardItem *item1 = new QStandardItem(QString(value.c_str()));
            propertyModel->setItem(i,1, item1);

            int type = tool->getPropertyType(props[i]);
            QStandardItem *item2 = new QStandardItem(QString("%0").arg(type));
            propertyModel->setItem(i,2, item2);

            string listModel = tool->getPropertyListModel(props[i]);
            QStandardItem *item3 = new QStandardItem(QString(listModel.c_str()));
            propertyModel->setItem(i,3, item3);
        }
    }
    propertyModel->setHeaderData(0, Qt::Horizontal, QString("Parameter"));
    propertyModel->setHeaderData(1, Qt::Horizontal, QString("Value"));

    table->setItemDelegate(createDelegate(controller, this));
    table->setColumnHidden(2, true);
    table->setColumnHidden(3, true);
    table->resizeColumnToContents(0);
    table->horizontalHeader()->setStretchLastSection(true);

    currentTool = tool;
}


void Transforms::propertyChanged(QStandardItem *item) {
    if(!currentTool) return;
    int row = item->index().row();

    string value = item->data(Qt::EditRole).toString().toStdString();
    QStandardItem *itemProp = item->model()->item(row,0);
    string property = itemProp->data(Qt::EditRole).toString().toStdString();

    controller->setToolProperty(currentTool, property, value);
}

/*********************** LAYOUTS **************************/
Layouts::Layouts(Controller *controller, QWidget *parent):QWidget(parent) {
    setWindowTitle("Layout");
    this->controller = controller;

    QVBoxLayout *uiLayout = new QVBoxLayout();

    vector<LayoutInfo> layouts = controller->getLayouts();

    // Create tree of transforms
    tree = new QTreeView(this);
    model = new QStandardItemModel();
    root = model->invisibleRootItem();
    for(unsigned int i=0;i<layouts.size();i++) {
        string name = layouts[i].name;
        string type = layouts[i].type;

        if(types.find(type)==types.end()) {
            QStandardItem *parentItem = new QStandardItem(QString(type.c_str()));
            parentItem->setEditable(false);
            root->appendRow(parentItem);
            types[type] = parentItem;
        }
        QStandardItem *item = new QStandardItem(QString(name.c_str()));
        item->setEditable(false);
        QStandardItem *parent = types[type];
        assert(parent);
        parent->appendRow(item);
    }

    tree->setHeaderHidden(true);
    tree->setModel(model);
    connect(tree, SIGNAL(clicked(QModelIndex)), this, SLOT(clicked(QModelIndex)));



    table = new QTableView();
    propertyModel = new QStandardItemModel();
    connect(propertyModel, SIGNAL(itemChanged(QStandardItem *)), SLOT(propertyChanged(QStandardItem *)));

    table->setModel(propertyModel);
    table->setEditTriggers(QAbstractItemView::AllEditTriggers);


    QPushButton *button = new QPushButton("Go");
    connect(button, SIGNAL(clicked()), SLOT(computePressed()));


    progressBar = new QProgressBar();
    progressBar->setRange(0, 100);

    uiLayout->addWidget(tree);
    uiLayout->addWidget(table);
    uiLayout->addWidget(button);
    uiLayout->addWidget(progressBar);
    setLayout(uiLayout);

    controller->addLayoutListener(this);
}

void Layouts::setProgress(float value) {
    int iValue = (int) (value*100);
    progressBar->setValue(iValue);
    QCoreApplication::processEvents();
}
void Layouts::done() {
    progressBar->setValue(progressBar->maximum());
}

void Layouts::computePressed() {
    assert(controller);
    QItemSelectionModel * selection = tree->selectionModel();
    if(selection && selection->hasSelection()) {
        string name = selection->currentIndex().data().toString().toStdString();
        controller->executeLayout(name);
        controller->updateRender();
    }
}

void Layouts::layoutAdded(Layout *layout) {
    string type = layout->getType();
    string name = layout->getName();
    if(types.find(type) == types.end()) {
        QStandardItem *parentItem = new QStandardItem(QString(type.c_str()));
        parentItem->setEditable(false);
        root->appendRow(parentItem);
        types[type] = parentItem;
    }
    QStandardItem *item = new QStandardItem(QString(name.c_str()));
    item->setEditable(false);
    QStandardItem *parent = types[type];
    assert(parent);
    parent->appendRow(item);
}


void Layouts::clicked(const QModelIndex &index) {
    assert(propertyModel);
    currentLayout = 0;
    propertyModel->clear();

    QStandardItem *item = model->itemFromIndex(index);
    string name = item->data(Qt::EditRole).toString().toStdString();

    Layout *layout = controller->getLayout(name);
    if(layout) {
        layout->setProgressListener(this);
        vector<string> props = layout->getProperties();

        for(unsigned int i=0;i<props.size();i++) {
            QStandardItem *item = new QStandardItem(QString(props[i].c_str()));
            propertyModel->setItem(i,0, item);
            item->setEditable(false);

					string value = layout->getAsString(props[i]);

            QStandardItem *item1 = new QStandardItem(QString(value.c_str()));
            propertyModel->setItem(i,1, item1);

            int type = layout->getPropertyType(props[i]);
            QStandardItem *item2 = new QStandardItem(QString("%0").arg(type));
            propertyModel->setItem(i,2, item2);

            string listModel = layout->getPropertyListModel(props[i]);
            QStandardItem *item3 = new QStandardItem(QString(listModel.c_str()));
            propertyModel->setItem(i,3, item3);
        }
    }
    propertyModel->setHeaderData(0, Qt::Horizontal, QString("Parameter"));
    propertyModel->setHeaderData(1, Qt::Horizontal, QString("Value"));

    table->setItemDelegate(createDelegate(controller, this));
    table->setColumnHidden(2, true);
    table->setColumnHidden(3, true);
    table->resizeColumnToContents(0);
    table->horizontalHeader()->setStretchLastSection(true);

    currentLayout = layout;
}


void Layouts::propertyChanged(QStandardItem *item) {
    if(!currentLayout) return;
    int row = item->index().row();

    string value = item->data(Qt::EditRole).toString().toStdString();
    QStandardItem *itemProp = item->model()->item(row,0);
    string property = itemProp->data(Qt::EditRole).toString().toStdString();

    controller->setLayoutProperty(currentLayout, property, value);
    currentLayout->update(property);
}

Datatab::Datatab(Controller *controller, QWidget *parent):QWidget(parent) {
    this->controller = controller;
    QVBoxLayout *layout = new QVBoxLayout();

    //QLabel *sources = new QLabel("TEST");
    //layout->addWidget(sources);

    QDataEditor *dataWidget = new QDataEditor(controller, this);
    //QMappingEditor *mapping = new QMappingEditor(controller, this);
    layout->addWidget(dataWidget);
    setLayout(layout);
}

void Datatab::dataAdded(const char */*source*/, string /*event*/){
    // do nothing here
    // reload the data again
}
